import os
import logging
from typing import Dict, Optional, Tuple

# 日志配置
logging.basicConfig(level=logging.INFO)
logger = logging.getLogger("opensearch_config")

class ConfigError(Exception):
    """配置相关异常"""
    pass

class SearchWeightConfig:
    """
    检索权重配置，支持环境变量和代码传参，权重总和校验，支持动态调整。
    """
    def __init__(self,
                 keyword_weight: Optional[float] = None,
                 vector_weight: Optional[float] = None,
                 hybrid_enabled: Optional[bool] = None) -> None:
        self.keyword_weight, self.vector_weight = self._load_weights(keyword_weight, vector_weight)
        self.hybrid_enabled = self._load_hybrid_enabled(hybrid_enabled)
        self._validate_weights()
        logger.info(f"初始化权重配置: keyword={self.keyword_weight}, vector={self.vector_weight}, hybrid={self.hybrid_enabled}")

    def _load_weights(self, keyword_weight: Optional[float], vector_weight: Optional[float]) -> Tuple[float, float]:
        # 优先代码传参，其次环境变量，最后默认
        kw = keyword_weight if keyword_weight is not None else float(os.getenv("KEYWORD_WEIGHT", "0.5"))
        vw = vector_weight if vector_weight is not None else float(os.getenv("VECTOR_WEIGHT", "0.5"))
        return kw, vw

    def _load_hybrid_enabled(self, hybrid_enabled: Optional[bool]) -> bool:
        if hybrid_enabled is not None:
            return hybrid_enabled
        env_val = os.getenv("HYBRID_ENABLED", "true").lower()
        return env_val in ("1", "true", "yes")

    def _validate_weights(self) -> None:
        total = self.keyword_weight + self.vector_weight
        if not abs(total - 1.0) < 1e-6:
            logger.error(f"权重总和校验失败: keyword={self.keyword_weight}, vector={self.vector_weight}")
            raise ConfigError("关键词权重与向量权重之和必须为1")
        if not (0.0 <= self.keyword_weight <= 1.0 and 0.0 <= self.vector_weight <= 1.0):
            logger.error(f"权重范围校验失败: keyword={self.keyword_weight}, vector={self.vector_weight}")
            raise ConfigError("权重必须在0到1之间")

    def update_weights(self, keyword_weight: float, vector_weight: float) -> None:
        logger.info(f"动态调整权重: keyword={keyword_weight}, vector={vector_weight}")
        self.keyword_weight = keyword_weight
        self.vector_weight = vector_weight
        self._validate_weights()

    def set_hybrid_enabled(self, enabled: bool) -> None:
        logger.info(f"设置混合检索开关: {enabled}")
        self.hybrid_enabled = enabled

    def as_dict(self) -> Dict[str, float]:
        return {
            "keyword_weight": self.keyword_weight,
            "vector_weight": self.vector_weight,
            "hybrid_enabled": self.hybrid_enabled
        } 